package net.csdn.business.common.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONPath;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.List;

/**
 * @author likun
 * @date 2022/6/17 12:58
 */
public class JsonUtil {
    public static JSONObject toJsonObject(Object value, JSONWriter.Feature... features) {
        if (value == null) {
            return new JSONObject();
        }
        JSONObject result;
        if (value instanceof String) {
            result = JSON.parseObject((String) value);
        } else if (value instanceof JSONObject) {
            result = (JSONObject) value;
        } else {
            result = JSON.parseObject(toJsonString(value, features), JSONObject.class);
        }
        if (result == null) {
            result = new JSONObject();
        }
        return result;
    }

    public static String toJsonString(Object obj, JSONWriter.Feature... features) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof String) {
            return (String) obj;
        }
        return JSON.toJSONString(obj, features);
    }

    @SneakyThrows
    public static <T> T toBean(Object value, Class<T> type) {
        T result = toBeanMayNull(value, type);
        if (result == null) {
            result = type.newInstance();
        }
        return result;
    }

    @SneakyThrows
    public static <T> T toBeanMayNull(Object value, Class<T> type, String... excludes) {
        T result;
        if (value instanceof String) {
            String v = (String) value;
            result = JSON.parseObject(v, type);
        } else if (value instanceof byte[]) {
            result = JSON.parseObject((byte[]) value, type);
        } else {
            SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
            for (String exclude : excludes) {
                if (exclude != null) {
                    filter.getExcludes().add(exclude);
                }
            }
            String v = JSON.toJSONString(value, filter);
            result = JSONObject.parseObject(v, type);
        }
        return result;
    }

    public static List<JSONObject> toList(Object v) {
        if (null == v) {
            return null;
        }
        String value;
        if (v instanceof String) {
            value = v.toString();
        } else {
            value = JSON.toJSONString(v);
        }
        return JSON.parseArray(value, JSONObject.class);
    }

    public static Object getValueByKey(JSONObject param, String path) {
        if (CollectionUtils.isEmpty(param) || StringUtils.isEmpty(path)) {
            return null;
        }
        return JSONPath.eval(param, path);
    }

    public static <T> T getValueByKey(JSONObject param, String path, Class<T> clazz) {
        if (CollectionUtils.isEmpty(param) || StringUtils.isEmpty(path)) {
            return null;
        }
        Object o = JSONPath.eval(param, path);
        if (ObjectUtils.isEmpty(o)) {
            return null;
        }
        return JSONObject.parseObject(JSON.toJSONString(o), clazz);
    }

    public static JSONObject mergeJson(JSONObject a, JSONObject b) {
        if (ObjectUtils.isEmpty(a)) {
            return b;
        }
        if (ObjectUtils.isEmpty(b)) {
            return a;
        }
        for (String key : a.keySet()) {
            b.put(key, a.get(key));
        }
        return b;
    }
}